{UTF-8}
Unit Process;
Interface
Uses routine;
Const
	NEVER:longint = -1;
Type
		body_process = procedure;
		id_type = word;
		PProcess = ^TProcess;
		TProcess = Object
				Private
						{id процесса}
						id:							id_type;
						{дескриптор процесса}
						descriptor:					descptr;
						{указатель на стэк процесса}
						stackptr:					arptr;
						{Приватное поле типа Procedure, в котором
						хранятся действия процесса}
                        running:					body_process;
						{время для активизации}
						takt_activisation:			longint;
                        {создание новой сопрограммы}
						Procedure       newProcess(b:pointer;var d:descptr);
                Public
                        {конструктор класса, в качестве параметра
						указывается процедура, которая должна
						быть телом процесса}
                        Constructor init(arg:body_process; pid:id_type);
                        Destructor  done;
                        {передача управления другому процессу по процессу}
                        Procedure       TransferByProcess(other:TProcess);
                        {передача управления другому процессу по дескриптору}
                        Procedure       TransferByDescriptor(other:descptr);
                        {метод возвращает descriptor данного процесса}
                        function        get_descriptor:descptr;
                        Function        get_id:id_type;
						Procedure		set_id(const arg:id_type);
                        {метод выводит на экран значения основных
						полей процесса}
						{id, ssreg, spreg}
						Procedure       printInfo;
						{метод устанавливает значение поля takt_activisation }
						Procedure		set_takt(const t:longint);
						{метод возвращает значение поля takt_activisation}
						Function		get_takt:longint;
						{метод сравнивает два процесса на идентичность}
						{по id, descptr и takt_activisation}
						Function		equal(other:TProcess):boolean;
        end;
Implementation
 
procedure TProcess.newProcess;
var
        ar : arptr;
begin
        new(ar);
        new(d);
        with d^ do begin
                ssreg:=seg(ar^);
                spreg:=ofs(ar^) + 1998 - 14;
                memw[ssreg:spreg+2] := ofs(b^);
                memw[ssreg:spreg+4] := seg(b^);        
        end;
end;
Constructor TProcess.init;
begin
        takt_activisation := NEVER;
		running:=arg;
        newProcess(@running, descriptor);
        id:=pid;
        {stackptr:=ptr(seg(stack), ofs(stack))}
        stackptr:=ptr(descriptor^.ssreg, (descriptor^.spreg-1998+14));
end;
Destructor TProcess.Done;
begin
        writeln('destructor of process ', id);
        if stackptr<>nil then dispose(stackptr);
        if (descriptor <> nil) then dispose(descriptor);
end;
Procedure TProcess.TransferByProcess;
begin
        Transfer(descriptor, other.get_descriptor);
end;
Procedure TProcess.TransferByDescriptor;
begin
        Transfer(descriptor, other);
end;
 
function TProcess.get_descriptor:descptr;
begin
        get_descriptor:=descriptor;
end;
function TProcess.get_id;
begin
        get_id:=id;
end;
procedure       TProcess.printInfo ;
begin
        writeln('pid:', id);
        if (descriptor = nil) then
                writeln('descpr: nil')
        else
                begin
                        writeln('ssreg:', descriptor^.ssreg);
                        writeln('spreg:', descriptor^.spreg);
                end;
end;
Procedure TProcess.set_takt;
begin
	takt_activisation:=t;
end;
Function TProcess.get_takt;
begin
	get_takt:=takt_activisation;
end;
Function TProcess.equal;
begin
	if ((id = other.get_id) and (descriptor = other.get_descriptor) 
		and (takt_activisation = other.get_takt)) then
		equal:=true
	else
		equal:=false;
end;
Procedure TProcess.set_id;
begin
	id:=arg;
end;
end.